﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using System.Data;
using VehicleScale.EntityMappers;
using VehicleScale.Models;
using System.Diagnostics;

namespace VehicleScale.DataAccess
{
    public class EmployeeDataAccess : BaseDataAccess, IEmployeeDataAccess
    {

        #region Properties

        private EmployeeModel _searchObject;
        /// <summary>
        /// Search Object Property
        /// </summary>
        public EmployeeModel SearchObject
        {
            get { return _searchObject; }
            set
            {
                if (_searchObject != value)
                {
                    _searchObject = value;
                }
            }
        }

        #endregion

        #region Methods
        /// <summary>
        /// Search Method
        /// </summary>
        /// <returns></returns>
        public IList<EmployeeModel> Searcher()
        {
            IList<EmployeeModel> collection = null;
            try
            {
                using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
                {
                    IQueryable<Employee> query = dataContext.Employees;
                    if (!String.IsNullOrEmpty(_searchObject.EmployeeID))
                    {
                        query = query.Where(e => e.EmployeeID.Contains(_searchObject.EmployeeID));
                    }
                    if (!String.IsNullOrEmpty(_searchObject.EmployeeName))
                    {
                        query = query.Where(e => e.EmployeeName.Contains(_searchObject.EmployeeName));
                    }
                    if (!String.IsNullOrEmpty(_searchObject.Telephone))
                    {
                        query = query.Where(e => e.Telephone.Contains(_searchObject.Telephone));
                    }
                    if (!String.IsNullOrEmpty(_searchObject.Address))
                    {
                        query = query.Where(e => e.Address.Contains(_searchObject.Address));
                    }
                    if (!String.IsNullOrEmpty(_searchObject.Identification))
                    {
                        query = query.Where(e => e.Identification.Contains(_searchObject.Identification));
                    }
                    if (!String.IsNullOrEmpty(_searchObject.Username))
                    {
                        query = query.Where(e => e.Username.Contains(_searchObject.Username));
                    }

                    collection = new List<EmployeeModel>();
                    foreach (var item in query)
                    {
                        collection.Add(EmployeeMapper.ToModel(item));
                    }
                }

                return collection;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Get all Method
        /// </summary>
        /// <returns></returns>
        public IList<EmployeeModel> GetAll()
        {
            IList<EmployeeModel> collection;
            using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
            {
                IQueryable<Employee> query = dataContext.Employees;

                collection = new List<EmployeeModel>();
                foreach (var item in query)
                {
                    collection.Add(EmployeeMapper.ToModel(item));
                }
            }

            return collection;
        }
        
        /// <summary>
        /// Get Method
        /// </summary>
        /// <returns></returns>
        public EmployeeModel Get()
        {
            EmployeeModel item = null;
            using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
            {
                Employee query = dataContext.Employees.FirstOrDefault();

                if (query != null) 
                    item = EmployeeMapper.ToModel(query);
            }

            return item;
        }
        
        /// <summary>
        /// Get Last Method
        /// </summary>
        /// <returns></returns>
        public EmployeeModel GetLast()
        {
            EmployeeModel item = null;
            using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
            {
                Employee query = dataContext.Employees.LastOrDefault();

                if (query != null) item = EmployeeMapper.ToModel(query);
            }

            return item;
        }

        /// <summary>
        /// Get by. This uses in authencation.
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public EmployeeModel GetBy(string username, string password)
        {
            EmployeeModel model = null;
            using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
            {
                var query = dataContext.Employees.Where(
                    e => e.Username == username && 
                    e.Password == password &&
                    e.Active).FirstOrDefault();

                if (query != null)
                {
                    model = EmployeeMapper.ToModel(query);
                }
            }

            return model;
        }
        
        /// <summary>
        /// Generate Auto ID Method
        /// </summary>
        /// <param name="dataContext"></param>
        /// <returns></returns>
        private string GenerateAutoID(DataClassesDataContext dataContext)
        {
            string id = String.Empty;
            int length = 20; // length default
            string prefix = String.Empty;
            string startNumber = "1";
            string defaultID = String.Empty;

            // Create Default Key
            Config config = dataContext.Configs.FirstOrDefault();
            if (config != null)
            {
                prefix = config.EmployeePrefix;
                length = config.EmployeeCodeLength;
            }
            defaultID = prefix + startNumber.PadLeft(length, '0');

            // Create Automation Key
            var query = dataContext.Employees.Where(e =>
                e.EmployeeID.StartsWith(prefix));
            if (query != null)
                id = query.Max(e => e.EmployeeID);

            if (String.IsNullOrEmpty(id))
                id = defaultID;
            else
            {
                id = id.Remove(0, prefix.Length);
                int numberID;
                string suffix;
                if (Int32.TryParse(id, out numberID))
                {
                    numberID++;
                    suffix = numberID.ToString().PadLeft(length, '0');
                    id = prefix + suffix;
                }
                else
                {
                    id = defaultID;
                }
            }
            // End Create Automation Key
            return id;
        }
        
        /// <summary>
        /// Add Method
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Add(EmployeeModel item)
        {
            bool result = false;
            try
            {
                using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
                {
                    if (String.IsNullOrEmpty(item.EmployeeID))
                    {
                        item.EmployeeID = GenerateAutoID(dataContext);
                    }

                    Employee entity = new Employee();
                    EmployeeMapper.ToEntity(entity, item);
                    dataContext.Employees.InsertOnSubmit(entity);
                    dataContext.SubmitChanges();
                    result = true;
                    item.IsNew = false;
                    item.IsEdit = false;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return result;
        }

        // Add Collection Method
        public bool Add(IList<EmployeeModel> collection)
        {
            throw new NotImplementedException();
        }
        
        /// <summary>
        /// Edit Method
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Edit(EmployeeModel item)
        {
            bool result = false;
            try
            {
                using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
                {
                    Employee entity = dataContext.Employees.Where(e => e.EmployeeID == item.EmployeeID).SingleOrDefault();
                    if (entity != null)
                    {
                        EmployeeMapper.ToEntity(entity, item);
                        dataContext.SubmitChanges();
                        result = true;
                        item.IsNew = false;
                        item.IsEdit = false;
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return result;
        }
        
        public bool Edit(IList<EmployeeModel> collection)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Delete Method
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Delete(EmployeeModel item)
        {
            bool result = false;
            try
            {
                using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
                {
                    Employee entity = dataContext.Employees.Where(e => e.EmployeeID == item.EmployeeID).SingleOrDefault();
                    dataContext.Employees.DeleteOnSubmit(entity);
                    dataContext.SubmitChanges();
                    result = true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return result;
        }

        public bool Delete(IList<EmployeeModel> collection)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Reset Password Method
        /// </summary>
        /// <param name="collection"></param>
        /// <returns></returns>
        public bool ResetPassword(IEnumerable<EmployeeModel> collection)
        {
            bool result = false;
            try
            {
                using (DataClassesDataContext dataContext = new DataClassesDataContext(base.ConnectionString))
                {
                    foreach (var item in collection)
                    {
                        var query = dataContext.Employees.Where(e => e.Username == item.Username).FirstOrDefault();

                        if (query != null)
                        {
                            query.Password = Library.Encrypt.Encrypt.Encode("MD5", Common.PasswordDefault);
                        }
                    }

                    dataContext.SubmitChanges();
                    result = true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            return result;
        }

        #endregion

    }
}
